package com.abai.doubi.server.controller;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.PageResult;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.abai.doubi.entity.Result;
import com.abai.doubi.entity.dto.ConversationHistoryDTO;
import com.abai.doubi.entity.dto.StartConversationDTO;
import com.abai.doubi.entity.dto.TextMessageDTO;
import com.abai.doubi.entity.dto.VoiceMessageDTO;
import com.abai.doubi.entity.pojo.Conversation;
import com.abai.doubi.entity.pojo.Role;
import com.abai.doubi.entity.pojo.RoleSkill;
import com.abai.doubi.entity.vo.ConversationHistoryVO;
import com.abai.doubi.entity.vo.ConversationSessionVO;
import com.abai.doubi.entity.vo.ConversationResponseVO;
import com.abai.doubi.server.config.AliConfig;
import com.abai.doubi.server.service.IChatService;
import com.abai.doubi.server.service.IConversationService;
import com.abai.doubi.server.service.IRoleService;
import com.abai.doubi.server.service.IRoleSkillService;
import com.abai.doubi.utils.*;
import com.alibaba.nls.client.protocol.NlsClient;
import com.alibaba.nls.client.protocol.OutputFormatEnum;
import com.alibaba.nls.client.protocol.SampleRateEnum;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizer;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizerListener;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizerResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.qiniu.util.Auth;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import reactor.core.publisher.Flux;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.abai.doubi.server.config.MQConfig.CONVERSATION_SAVE_EXCHANGE;
import static com.abai.doubi.server.config.MQConfig.CONVERSATION_SAVE_ROUTING_KEY;

//@CrossOrigin("*")
@RestController
@RequestMapping("/chat")
@Tag(name = "会话接口", description = "会话相关接口")
@Slf4j
public class ChatController {
    @Autowired
    private IChatService chatService;

    @Autowired
    private IRoleService roleService;

    @Autowired
    private IRoleSkillService roleSkillService;

    @Autowired
    private IConversationService conversationService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private OkHttpClient okHttpClient;

    @Autowired
    private AliSTTUtil aliSTTUtil;

    @Autowired
    private AliTTSUtil aliTTSUtil;


    /**
     * 开始对话会话
     * POST /api/conversation/start
     */
    @GetMapping("/start")
    @Operation(summary = "开始会话", description = "点击角色,即会话开始")
    public Result<ConversationSessionVO> startConversation(@RequestParam Long roleId){
        Long userId = ContextUtil.getCurrentId();
        String sessionId = UUID.randomUUID().toString();

        Role role = roleService.getById(roleId);
        if (role == null){
            return Result.error("系统出错,角色不存在");
        }
        ConversationSessionVO conversationSessionVO = ConversationSessionVO.builder()
                .sessionId(sessionId)
                .userId(userId)
                .roleId(role.getId())
                .roleName(role.getRoleName())
                .roleAvatar(role.getAvatarUrl())
                .createTime(role.getCreateTime())
                .build();
        return Result.<ConversationSessionVO>builder()
                .code(Result.SUCCESS_CODE)
                .data(conversationSessionVO)
                .build();
    }

    /**
     * 发送文本消息
     * POST /api/conversation/text
     */
    @GetMapping("/text")
    @Operation(summary = "文本消息对话", description = "使用文本进行对话")
//    public Flux<ChatResponse> sendTextMessage(String sessionId,String userMessage,String roleId){
    public SseEmitter sendTextMessage(String sessionId,String userMessage,Long roleId){
        try {
            // 构造对话需求信息（用于上下文理解）
            Role role = roleService.getById(roleId);
            List<Conversation> historys = conversationService.lambdaQuery()
                    .eq(Conversation::getSessionId, sessionId)
                    .orderByDesc(Conversation::getCreateTime)
                    .last("LIMIT 5")
                    .list();
            List<RoleSkill> roleSkills = roleSkillService.lambdaQuery()
                    .eq(RoleSkill::getRoleId, roleId)
                    .list();
            RoleSkill usedSkill = roleSkills.stream()
                    .filter(skill -> {
                        // 获取技能的关键词列表
                        List<String> keywords = JSONUtil.toList(skill.getTriggerKeywords(), String.class);
                        // 检查用户消息是否包含任何关键词
                        return keywords != null && keywords.stream()
                                .anyMatch(keyword -> userMessage.contains(keyword));
                    })
                    .findFirst()
                    .orElse(null);

            // 调用AI服务获取回复
            Flux<String> response = chatService.generateStreamReply(role,userMessage,usedSkill,historys);
            SseEmitter emitter = new SseEmitter(5 * 60 * 1000L);
            StringBuffer completeReply = new StringBuffer();
            AtomicLong startTime = new AtomicLong(System.currentTimeMillis());
            Long userId = ContextUtil.getCurrentId() == null ? 1L : ContextUtil.getCurrentId();
            response.subscribe(
                            content -> {
                                try {
                                    emitter.send(content);
                                    completeReply.append(content);
                                } catch (IOException e) {
                                    log.error("SSE发送数据失败", e);
                                }
                            },
                            error -> {
                                log.error("流式响应出错", error);
                                long responseTime = System.currentTimeMillis() - startTime.get();
                                saveConversation(Conversation.builder()
                                        .sessionId(sessionId)
                                        .userId(userId)
                                        .roleId(roleId)
                                        .messageType(1)
                                        .userMessage(userMessage)
                                        .roleMessage(completeReply.toString())
                                        .skillUsed(usedSkill == null ? null : usedSkill.getSkillName())
                                        .responseTime((int) responseTime)
                                        .build());
                                emitter.completeWithError(error);
                            },
                            () -> {
                                // 在这里保存完整的对话记录
                                long responseTime = System.currentTimeMillis() - startTime.get();
                                saveConversation(Conversation.builder()
                                        .sessionId(sessionId)
                                        .userId(userId)
                                        .roleId(roleId)
                                        .messageType(1)
                                        .userMessage(userMessage)
                                        .roleMessage(completeReply.toString())
                                        .skillUsed(usedSkill == null ? null : usedSkill.getSkillName())
                                        .responseTime((int) responseTime)
                                        .build());
                                log.info("会话结束");
                                try {
                                    emitter.send("[DONE]");
                                    emitter.complete();
                                } catch (IOException e) {
                                    throw new RuntimeException(e);
                                }
                            }

                    );
            return emitter;
        } catch (Exception e) {
            return null;
        }
    }

    private void saveConversation(Conversation conversation) {
        rabbitTemplate.convertAndSend(CONVERSATION_SAVE_EXCHANGE, CONVERSATION_SAVE_ROUTING_KEY,conversation);
    }

    /**
     * 发送语音消息
     * POST /api/chat/voice
     */
    @PostMapping(value ="/voice")
    @Operation(summary = "语音消息对话")
    public Result<ConversationResponseVO> sendVoiceMessage(@RequestParam("audioFile") MultipartFile audioFile,
                                                           @RequestParam("sessionId") String sessionId,
                                                           @RequestParam("roleId") Long roleId,
                                                           @RequestParam("userMessage") String userMessage){
        try {
            //语音文件存储进七牛云
            String userAudioName = sessionId + "_user_" + System.currentTimeMillis() + ".wav";
            String userAudioUrl = QiniuKodoUtil.upload(audioFile.getBytes(), userAudioName);

            userMessage = aliSTTUtil.processAndGetResult(audioFile, 16000);

            log.info("用户语音消息:{}", userMessage);
            Role role = roleService.getById(roleId);
            List<Conversation> historys = conversationService.lambdaQuery()
                    .eq(Conversation::getSessionId, sessionId)
                    .orderByDesc(Conversation::getCreateTime)
                    .last("LIMIT 5")
                    .list();
            List<RoleSkill> roleSkills = roleSkillService.lambdaQuery()
                    .eq(RoleSkill::getRoleId, roleId)
                    .list();
            String finalUserMessage = userMessage;
            RoleSkill usedSkill = roleSkills.stream()
                    .filter(skill -> {
                        // 获取技能的关键词列表
                        List<String> keywords = JSONUtil.toList(skill.getTriggerKeywords(), String.class);
                        // 检查用户消息是否包含任何关键词
                        return keywords != null && keywords.stream()
                                .anyMatch(keyword -> finalUserMessage.contains(keyword));
                    })
                    .findFirst()
                    .orElse(null);

            // 调用AI服务获取回复
            String reply = chatService.generateReply(role,userMessage,usedSkill,historys);

            //存在本地tts_test.wav
            long startTime = System.currentTimeMillis();
            aliTTSUtil.process(reply);
            long responseTime = System.currentTimeMillis() - startTime;

            String roleAudioName = sessionId + "_role_" + System.currentTimeMillis() + ".wav";
            String roleAudioUrl = QiniuKodoUtil.upload(IoUtil.readBytes(new FileInputStream("tts_test.wav"), true), roleAudioName);

            Long userId = ContextUtil.getCurrentId() == null ? 1L : ContextUtil.getCurrentId();
            ConversationResponseVO vo = ConversationResponseVO.builder()
                    .sessionId(sessionId)
                    .roleMessage(reply)
                    .roleVoiceUrl(roleAudioUrl)
                    .responseTime(responseTime)
                    .usedSkill(usedSkill == null ? null : usedSkill.getSkillName())
                    .build();
            saveConversation(Conversation.builder()
                    .sessionId(sessionId)
                    .userId(userId)
                    .roleId(roleId)
                    .messageType(2)
                    .userMessage(userMessage)
                    .roleMessage(reply)
                    .userVoiceUrl(userAudioUrl)
                    .RoleVoiceUrl(roleAudioUrl)
                    .skillUsed(usedSkill == null ? null : usedSkill.getSkillName())
                    .responseTime((int) responseTime)
                    .build());

            return Result.<ConversationResponseVO>builder()
                    .code(Result.SUCCESS_CODE)
                    .data(vo)
                    .build();
        } catch (Exception e) {
            return Result.error("语音消息发送失败: " + e.getMessage());
        }

    }

    /**
     * 获取对话历史
     * POST /api/chat/history
     */
    @PostMapping("/history")
    @Operation(summary = "获取对话历史")
    public Result<List<Conversation>> getConversationHistory(@RequestBody ConversationHistoryDTO dto){
        if (dto.getSessionId() == null) {
            return Result.error("sessionId不能为空!");
        }
        // 参数校验和默认值设置
        if (dto.getPageSize() == null || dto.getPageSize() <= 0) {
            dto.setPageSize(10);
        }
//        conversationService.lambdaQuery()
//                .eq(Conversation::getSessionId, dto.getSessionId())
//                .orderByDesc(Conversation::getId)
//                .last("limit " + dto.getPageSize())
//                .list();

        Long userId = ContextUtil.getCurrentId() == null ? 1L : ContextUtil.getCurrentId();
        // 构建查询条件
        LambdaQueryChainWrapper<Conversation> queryWrapper = conversationService.lambdaQuery()
                .eq(Conversation::getUserId, userId)
                .eq(Conversation::getSessionId, dto.getSessionId())
                .orderByDesc(Conversation::getId);

        // 只有当lastId有值时才添加lt条件
        if (dto.getLastId() != null && dto.getLastId() > 0) {
            queryWrapper.lt(Conversation::getId, dto.getLastId());
        }

        List<Conversation> records = queryWrapper
                .last("limit " + dto.getPageSize())
                .list();
        return Result.<List<Conversation>>builder()
                .code(Result.SUCCESS_CODE)
                .data(records)
                .build();
    }

    /**
     * 获取历史对话id列表
     * GET /api/chat/historyList
     */
    @GetMapping("/historyList")
    @Operation(summary = "获取历史对话id列表")
    public Result<List<ConversationHistoryVO>> getConversationHistoryList(@RequestParam String roleId){
        if (roleId == null) {
            return Result.error("roleId不能为空!");
        }
        Long userId = ContextUtil.getCurrentId() == null ? 1L : ContextUtil.getCurrentId();
        // 构建查询条件
//        List<String> historyIdList = conversationService.lambdaQuery()
//                .eq(Conversation::getUserId, userId)
//                .eq(Conversation::getRoleId, roleId)
//                .orderByDesc(Conversation::getId)
//                .list()
//                .stream()
//                .map(Conversation::getSessionId)
//                .distinct()
//                .toList();

        // 如果MyBatis Plus支持原生SQL
        List<Conversation> firstConversations = conversationService.getBaseMapper()
                .selectList(new QueryWrapper<Conversation>()
                .eq("user_id", userId)
                .eq("role_id", roleId)
                .inSql("id", "SELECT MIN(id) FROM conversation WHERE user_id = " + userId + " AND role_id = " + roleId + " GROUP BY session_id"));
        List<ConversationHistoryVO> historyIdList = firstConversations.stream()
                .map(conversation -> ConversationHistoryVO.builder()
                        .sessionId(conversation.getSessionId())
                        .keyMessage(conversation.getUserMessage())
                        .build())
                .toList();
        return Result.<List<ConversationHistoryVO>>builder()
                .code(Result.SUCCESS_CODE)
                .data(historyIdList)
                .build();
    }

    /**
     * 获取历史对话id列表
     * GET /api/chat/historyList
     */
    @GetMapping("/delete")
    @Operation(summary = "删除会话")
    public Result deleteConversation(@RequestParam String sessionId) {
        if (sessionId == null) {
            return Result.error("sessionId不能为空!");
        }
        boolean remove = conversationService.lambdaUpdate()
                .eq(Conversation::getSessionId, sessionId)
                .remove();
        if (remove){
            return Result.success("删除成功");
        }else {
            return Result.error("删除失败");
        }
    }



}
